home *** CD-ROM | disk | FTP | other *** search
/ Aminet 35 / Aminet 35 (2000)(Schatztruhe)[!][Feb 2000].iso / Aminet / game / shoot / ADescentSrc.lha / descent / Amiga / amiga_socket.c < prev    next >
C/C++ Source or Header  |  1999-08-29  |  9KB  |  331 lines

  1. /*
  2. ** Amiga_socket
  3. ** Amiga socket i/o stuff for point-to-point
  4. **
  5. ** $Id: amiga_socket.c,v 1.3 1998/04/25 08:39:20 nobody Exp $
  6. ** $Revision: 1.3 $
  7. ** $Author: nobody $
  8. ** $Date: 1998/04/25 08:39:20 $
  9. **
  10. ** $Log: amiga_socket.c,v $
  11. ** Revision 1.3  1998/04/25 08:39:20  nobody
  12. ** Changed configuration settings
  13. **
  14. ** Revision 1.2  1998/04/24 14:20:24  tfrieden
  15. ** Some stuff added
  16. **
  17. ** Revision 1.1  1998/04/14 23:58:01  tfrieden
  18. ** Initial checkin
  19. **
  20. */
  21.  
  22. #include <sys/types.h>
  23. #include <sys/time.h>
  24. #include <sys/socket.h>
  25. #include <sys/wait.h>
  26. #include <netinet/in.h>
  27. #include <errno.h>
  28. #include <fcntl.h>
  29. #include <netdb.h>
  30. #include <exec/types.h>
  31. #include "types.h"
  32. #include "args.h"
  33. #include "multi.h"
  34. #include "newmenu.h"
  35.  
  36. extern int errno;
  37. extern int message_length[];
  38. #define db_printf(a) /*  printf a */
  39.  
  40. #define DESCENT_DEFAULT_PORT    2345
  41. #define BUFFERLEN  1024
  42. #define ADD_ITEM(t,value,key)  do { m[num_options].type=NM_TYPE_MENU; menu_choice[num_options]=value; m[num_options].text=t; num_options++; } while (0)
  43.  
  44. int socket_fd = 0;                          //  Socket to opponent
  45. short socket_port = DESCENT_DEFAULT_PORT;   //  Port to use
  46. short socket_opened = 0;                    //  Is socket open ?
  47. short socket_other_valid = 0;               //  Set if opponents address is valid
  48. struct sockaddr_in socket_me;               //  My address
  49. struct sockaddr_in socket_other;            //  My opponents address
  50. UBYTE socket_buffer[BUFFERLEN];             //  used to send and receive data
  51. char socket_hostname[256];                  //  Host name for opponent
  52. int socket_timeout = 10;                    //  timeout for connection in seconds
  53.  
  54.  
  55. /*  socket_address_prepare
  56. ****************************
  57. **  fill in a struct sockaddr_in
  58. */
  59. void socket_prepare_address(struct sockaddr_in *address, short port, struct hostent *he)
  60. {
  61.         address->sin_family         = AF_INET;
  62.         address->sin_port           = htons(socket_port);
  63.         address->sin_addr           = *((struct in_addr *)he->h_addr);
  64.         bzero(&(address->sin_zero[0]), sizeof(struct sockaddr_in));
  65. }
  66.  
  67.  
  68. /*  socket_close
  69. ******************
  70. **  close socket and adjust flags
  71. */
  72. void socket_close(void)
  73. {
  74.  
  75.     if (socket_opened) {
  76.         close(socket);
  77.         socket_opened = 0;
  78.         db_printf(("socket_close: socket closed\n"));
  79.     }
  80. }
  81.  
  82.  
  83.  
  84. /*  socket_init
  85. *****************
  86. **  Init: get hostnames (and stuff)
  87. */
  88. void socket_init(void)
  89. {
  90.     int i;
  91.     struct hostent *he;
  92.  
  93.     if (i = FindArg("-ip_port")) {                      //  user supplied port
  94.         socket_port = atoi(Args[i+1]);
  95.     } else {
  96.         socket_port = DESCENT_DEFAULT_PORT;             //  use default
  97.     }
  98.     db_printf(("socket_init: Using port %d\n", socket_port));
  99.  
  100.     bzero(&(socket_me), sizeof(struct sockaddr_in));    //  fill up socket struct
  101.     socket_me.sin_family        = AF_INET;
  102.     socket_me.sin_port          = htons(socket_port);
  103.     socket_me.sin_addr.s_addr   = INADDR_ANY;
  104.     db_printf(("socket_init: Got local address\n"));
  105.  
  106.     if (i = FindArg("-ip_target")) {                    //  target given on  command line
  107.         strcpy(socket_hostname, Args[i+1]);
  108.         if (!(he = gethostbyname((char *)Args[i+1]))) { //  try getting it
  109.             printf("Warning: cannot get address for host %s\n",
  110.                 Args[i+1]);
  111.             socket_other_valid = 0;
  112.         } else {
  113.             socket_prepare_address(&socket_other, socket_port, he);
  114.             socket_other_valid = 1;
  115.             db_printf(("socket_init: Set target host %s address to %lx\n", Args[i+1],
  116.                 socket_other.sin_addr.s_addr));
  117.         }
  118.     } else {
  119.         strcpy(socket_hostname, "*NONE*");
  120.     }
  121.  
  122.     atexit(socket_close);
  123. }
  124.  
  125.  
  126. /*  socket_open
  127. *****************
  128. **  open socket to given host
  129. **  returns:
  130. **      >0  ok
  131. **      0   no host, and no default
  132. **      -1  can`t create socket
  133. **      -2  can`t bind
  134. **      -3  can`t connect
  135. **      -4  unknown host
  136. */
  137. int socket_open(char *host)
  138. {
  139.  
  140.     int sin_size;
  141.     struct hostent *he;
  142.     struct timeval tv = { 10,0 };                       //  10 seconds timeout for socket
  143.  
  144.     if (socket_opened != 0) return 1;                   //  We are open, so assume all is set
  145.  
  146.     if (host == NULL && socket_other_valid == 0) {      //  No host, and no default *shrug*
  147.         db_printf(("socket_open: No host to open\n"));
  148.         return(0);
  149.     }
  150.  
  151.     if (host) {                                         //  If a host is given, use it
  152.         if (he = gethostbyname(host)) {                 //  Get host address
  153.             db_printf(("socket_init: Set target host address to %lx\n", socket_other.sin_addr.s_addr));
  154.             socket_prepare_address(&socket_other, socket_port, he);
  155.             socket_other_valid              = 1;
  156.         } else {
  157.             return(-4);
  158.         }
  159.     }
  160.  
  161.     // if we got here, we either got a valid host, or a default host
  162.  
  163.     db_printf(("socket_open: opening socket..."));
  164.     if ((socket_fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
  165.         db_printf(("can`t open socket (%d)\n", errno));
  166.         return(-1);
  167.     }
  168.     db_printf(("OK\n"));
  169.  
  170.     db_printf(("socket_open: trying to bind..."));
  171.     if ((bind(socket_fd, (struct sockaddr *)&socket_me, sizeof(struct sockaddr))) == -1) {
  172.         db_printf(("failed: %d\n", errno));
  173.         close(socket_fd);
  174.         return(-2);
  175.     }
  176.     db_printf(("OK\n"));
  177.  
  178.     //  set timeouts
  179. //    setsockopt(socket_fd, SOL_SOCKET, SO_SNDTIMEO, (void *)&tv, sizeof(struct timeval));
  180. //    setsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, (void *)&tv, sizeof(struct timeval));
  181.  
  182.  
  183.     db_printf(("socket_open: trying to connect..."));
  184.     if (connect(socket_fd, (struct sockaddr *)&socket_other, sizeof(struct sockaddr)) == -1) {
  185.         db_printf(("failed: %d\n", errno));
  186.         close(socket_fd);
  187.         return(-3);
  188.     }
  189.     db_printf(("OK\n"));
  190.  
  191.     socket_opened = 1;                                  //  Indicate we have an open socket
  192.     fcntl(socket_fd, F_SETFL, O_NONBLOCK);              //  to avoid hangups
  193.  
  194.     return(1);
  195. }
  196.  
  197.  
  198.  
  199. /*  socket_send_ptr
  200. *******************
  201. **  Send a data packet to our host
  202. **  The package is appended to a header with the following layout:
  203. **  'PACK'  Longword to indicate package start
  204. **  len     unsigned long, giving the length of the package *data*
  205. **  data    len data bytes
  206. */
  207. void socket_send_ptr(char *ptr, int len)
  208. {
  209.     int nbytes;
  210.  
  211.     db_printf(("socket_send_ptr: going to send %d byte package\n", len));
  212.  
  213.     socket_buffer[0] = 'P';                         //  Build header
  214.     socket_buffer[1] = 'A';
  215.     socket_buffer[2] = 'C';
  216.     socket_buffer[3] = 'K';
  217.     *((ULONG *)(&socket_buffer[4])) = (ULONG)len;
  218.     memcpy(&socket_buffer[8], ptr, len);            //  Copy data to be send
  219.  
  220.     db_printf(("socket_send_ptr: Package ready to send (%d)\n", ptr[0]));
  221.  
  222.     nbytes = send(socket_fd, socket_buffer, len+8, 0);
  223.  
  224.     if (nbytes != len+8) {
  225.         db_printf(("socket_send_ptr: Error sending package: %d\n", errno));
  226.     }
  227.  
  228.     db_printf(("Sent package %d, length %d\n", *ptr, len));
  229.     return;
  230. }
  231.  
  232.  
  233. /*  socket_receive_ptr
  234. ************************
  235. **  check the socket for an incoming data package
  236. **  returns:
  237. **      0   indicate partial message read
  238. **      -1  no character was available (i.e. nothing to read)
  239. **      -2  a full message has been read
  240. **      -3  "carrier lost"
  241. **  The received data is put into the data area pinted to by ptr,
  242. **  and len is set to the number of data bytes read
  243. */
  244. int socket_receive_ptr(char *ptr, int *len)
  245. {
  246.     ULONG packhdr = 'P'<<24 | 'A'<<16 | 'C'<<8 | 'K';
  247.     int nbytes, olen;
  248.     ULONG *buf = (ULONG *)&socket_buffer[0];
  249.     ULONG length;
  250.  
  251.     db_printf(("socket_receive_ptr: trying socket\n"));
  252.  
  253.     nbytes = recv(socket_fd, socket_buffer, BUFFERLEN, 0);
  254.  
  255.     if (nbytes == -1 && errno == EWOULDBLOCK) {         //  nothing to receive
  256.         db_printf(("socket_receive_ptr: nothing to get\n"));
  257.         *len = 0;
  258.         return(-1);
  259.     }
  260.  
  261.     if (nbytes == -1) {                                 //  error
  262.         db_printf(("socket_receive_ptr: Error %d\n", errno));
  263.         *len = 0;
  264.         return(-1);                                     //  perhaps -3 ?
  265.     }
  266.  
  267.     if (buf[0] != packhdr) {                            //  error, wrong packet
  268.         db_printf(("socket_receive_ptr: Unknown packet received\n"));
  269.         *len = 0;
  270.         return(-1);
  271.     }
  272.  
  273.  
  274.     length = buf[1];                                    //  get length from header
  275.     db_printf(("socket_receive_ptr: got packet %x, length %d\n", buf[0], length));
  276.     memcpy(ptr, &socket_buffer[8], length);             //  copy the data bytes
  277.     *len = length;
  278.  
  279.     db_printf(("got packet %d, length %d (should be %d)\n",
  280.         socket_buffer[8], length-3, message_length[socket_buffer[8]]));
  281.     return -2;
  282. }
  283.  
  284.  
  285. /*  socket_param_setup
  286. ************************
  287. **  setup parameters for socket game
  288. */
  289. void socket_param_setup(void) {
  290.  
  291.     newmenu_item m[10];
  292.     int choice = 0;
  293.     int num_options = 0;
  294.     char text[2][256];
  295.     int i;
  296.  
  297.     strcpy(text[0], socket_hostname);
  298.     sprintf(text[1], "%d", (int)socket_port);
  299.     db_printf(("socket_param_setup: Host is %s:%s (%hd)\n", text[0], text[1], socket_port));
  300.  
  301.   /*  do {*/
  302.         m[0].type       = NM_TYPE_TEXT;
  303.         m[0].text       = "Hostname:";
  304.         m[1].type       = NM_TYPE_INPUT;
  305.         m[1].text_len   = 60;
  306.         m[1].text       = text[0];
  307.  
  308.         m[2].type       = NM_TYPE_TEXT;
  309.         m[2].text       = "Port:";
  310.         m[3].type       = NM_TYPE_INPUT;
  311.         m[3].text_len   = 8;
  312.         m[3].text       = text[1];
  313.  
  314.         m[4].type       = NM_TYPE_SLIDER;
  315.         m[4].text       = "Connection Timeout";
  316.         m[4].value      = socket_timeout/10;
  317.         m[4].min_value  = 0;
  318.         m[4].max_value  = 10;
  319.  
  320.         i = newmenu_do1( NULL, "TCP/IP options", 4, m, NULL, i);
  321.  
  322. /*    } while (i > -1);*/
  323.  
  324.     strcpy(socket_hostname, text[0]);
  325.     socket_port = atoi(text[1]);
  326.  
  327.     db_printf(("socket_param_setup: Set target to %s:%ud\n", socket_hostname, socket_port));
  328.  
  329.  
  330. }
  331.